package com.maxima.attendance.reports;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import com.maxima.attendance.daos.HolidayDAO;
import com.maxima.attendance.daos.ProjectDAO;
import com.maxima.attendance.daos.TimeLogDAO;
import com.maxima.attendance.daos.UserDAO;
import com.maxima.attendance.pojos.Holiday;
import com.maxima.attendance.pojos.Project;
import com.maxima.attendance.pojos.TimeLog;
import com.maxima.attendance.pojos.User;
import com.maxima.attendance.utils.DateOperations;

public class Report {
	private static List<Holiday> holidayList = new HolidayDAO()
			.getAllHolidays();
	private static Date currentDate =DateOperations.setZeroTime(new Date());
//	private static SimpleDateFormat dateFormat = new SimpleDateFormat(
//			"dd-MM-yyyy");

	public List<File> getReportFiles(Date date) {
			List<TimeLog> tList = new TimeLogDAO().getTimeLogsForMonth(date);

			Map<Integer,Project> projectMap = new HashMap<Integer,Project>();
			ProjectDAO projectDAO = new ProjectDAO();
			
			List<Project> projects= projectDAO.getAll();
			for (Project project : projects) {
				projectMap.put(project.getId(), project);
			}
			
			UserDAO userDAO = new UserDAO();
			Map<Integer,User> userMap = new HashMap<Integer,User>();
			
			List<User> allUsers = userDAO.getAllActiveUsers();
			for (User user : allUsers) {
				userMap.put(user.getId(), user);
			}
			
			Map<Project,List<User>> projectUserMap = new HashMap<Project,List<User>>();
			
			for (User user : allUsers) {
				if (projectUserMap.containsKey(user.getProject())) {
					projectUserMap.get(user.getProject()).add(user);
				} else {
					List<User> list = new ArrayList<User>();
					list.add(user);
					projectUserMap.put(user.getProject(), list);
				}
			}
			Map<User, List<TimeLog>> usertimeLogsMap = new HashMap<User, List<TimeLog>>();

			for (User user : allUsers) {
				usertimeLogsMap.put(user, new ArrayList<TimeLog>());
			}

			for (TimeLog timeLog : tList) {
				User user=userMap.get(timeLog.getUserId());
				if (usertimeLogsMap.containsKey(user)) {
					usertimeLogsMap.get(user).add(timeLog);
				} else {
					List<TimeLog> lst = new ArrayList<TimeLog>();
					lst.add(timeLog);
					usertimeLogsMap.put(user, lst);
				}
			}
			Calendar cal = Calendar.getInstance();
			cal.setTime(DateOperations.getFirstDateOfMonth(date));
			for (Map.Entry<User, List<TimeLog>> entry : usertimeLogsMap
					.entrySet()) {
				List<TimeLog> lst = new ArrayList<TimeLog>();
				cal.setTime(DateOperations.getFirstDateOfMonth(date));
				for (int i = 1; i <= cal.getActualMaximum(Calendar.DAY_OF_MONTH); i++) {
					
					cal.add(Calendar.DAY_OF_MONTH, 1);
					Date recordDate =DateOperations.setZeroTime(cal.getTime()); 
					if (recordDate.before(currentDate)) {
						TimeLog x = null;
						for (TimeLog timeLog : entry.getValue()) {
							if (DateOperations.setZeroTime(timeLog.getRecordDate()).equals(recordDate)) {
								x = timeLog;
								break;
							}
						}
						if (x == null) {
							lst.add(new TimeLog(recordDate, entry.getKey().getId(), checkIfHoliday(recordDate)));
						} else {
							lst.add(x);
						}
					} else {
						break;
					}
				}
				entry.setValue(lst);
			}
			CreateReport createReport = new CreateReport();
			List<File> files = new ArrayList<File>();
			for (Map.Entry<Project, List<User>> entry : projectUserMap.entrySet()) {

				Map<Integer, Object[]> data = formatData(usertimeLogsMap,
						entry);
				files.add(createReport.generateReport(entry.getKey().getProjectName()+ " - "+entry.getKey().getAgreement(), data));
			}
			return files;
	}

	public Map<Integer, Object[]> formatData(Map<User, List<TimeLog>> usertimeLogsMap, Map.Entry<Project, List<User>> entry) {
		int count;
		count = 0;
		Map<Integer, Object[]> data = new TreeMap<Integer, Object[]>();
		data.put(count++, new Object[] { "User", "Date", "Login Time",
				"Logout Time", "Total No of Hrs" });
		data.put(count++, new Object[] {});
		
		SimpleDateFormat timeFormat= new SimpleDateFormat("HH:mm");
		SimpleDateFormat dateFormat= new SimpleDateFormat("dd-MM-yyyy");
		for (User user : entry.getValue()) {
			for (TimeLog timeLog : usertimeLogsMap.get(user)) {
				if (timeLog.getLoginTime() != null
						&& timeLog.getLogoutTime() != null) {
					data.put(
							count++,
							new Object[] {
									user.getFirstName() + " " +user.getLastName(),
									dateFormat.format(timeLog.getRecordDate()), timeFormat.format(timeLog.getLoginTime()),
									timeFormat.format(timeLog.getLogoutTime()), getTimeDiff(timeLog) });

				}/* else if (timeLog.getLoginTime() != null) {
					data.put(
							count++,
							new Object[] {
									user.getFirstName() + " " +user.getLastName(),
									dateFormat.format(timeLog.getRecordDate()), timeFormat.format(timeLog.getLoginTime()),
									"-", "-" });
				}*/ else if(timeLog.getLoginTime()!=null && timeLog.getLogoutTime()==null){
					data.put(
							count++,
							new Object[] {
									user.getFirstName() + " " +user.getLastName(),
									dateFormat.format(timeLog.getRecordDate()), timeLog.getComment() });
				}
				 else{
						data.put(
								count++,
								new Object[] {
										user.getFirstName() + " " +user.getLastName(),
										dateFormat.format(timeLog.getRecordDate()), timeLog.getComment() });
					}
			}
			data.put(count++, new Object[] {});
		}
		return data;
	}

	public String checkIfHoliday(Date rec_date) {
		SimpleDateFormat dayOfWeekFormat = new SimpleDateFormat("EEEE");
		if (dayOfWeekFormat.format(rec_date).equals("Saturday")
				|| dayOfWeekFormat.format(rec_date).equals("Sunday"))
			return "Weekly Off";
		else {
			for (Holiday holiday : holidayList) {
				if (rec_date.equals(holiday.getDate()))
					return "Holiday";
			}
		}
		return "Leave";
	}

	public String getTimeDiff(TimeLog timeLog) {
		// in milliseconds
		long diff = timeLog.getLogoutTime().getTime() - timeLog.getLoginTime().getTime();
		
//		long diffSeconds = diff / 1000 % 60;
		long diffMinutes = diff / (60 * 1000) % 60;
		long diffHours = diff / (60 * 60 * 1000) % 24;
		long diffDays = diff / (24 * 60 * 60 * 1000);
		
		if(diffDays>0){
			return diffDays+" Day(s) "+ diffHours + ":" + diffMinutes;
		}
		return diffHours + ":" + diffMinutes;
	}
}
